<template>
  <div class="chat" :style="{ height: innerH + 'px' }">
    <chat-menu
      :chatMenu="leftMenuItem"
      :roomId="newToUserId"
      v-if="status === '876ea4f21078c7d38e3b0bdc74a'"
      @sendMessageToJoinRoom="joinNewRoomToSendMessage"
      @seeCurrentUserMessage="seeCurrentUserMessage"
      @initChat="initChat"
    ></chat-menu>
    <div class="chatContainer" :style="{ height: innerH1 + 'px' }">
      <div class="chatBoxBox">
        <transition name="fadeIn">
          <div class="chatBoxScroll" v-if="chatItem.length !== 0">
            <chatBox v-for="(item, index) in chatItem" :chatInfo="item" :key="item.id"></chatBox>
          </div>
        </transition>
      </div>
      <div class="pc">
        <Textarea v-model="content" height="130px" :placeholder="ifLogin ? '欢迎聊天...' : '请先登录'" :disabled="!ifLogin"></Textarea>
        <Button class="pc-button" @click="sendMessage" :disabled="!ifLogin">发消息</Button>
      </div>

      <div class="mv">
        <input :disabled="!ifLogin" type="text" v-model="content" />

        <Button @click="sendMessage" :disabled="!ifLogin">发消息</Button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import chatBox from '../../components/chatBox.vue'
import chatMenu from '../../components/chatLeftMenu.vue'
import { ref, onMounted, computed, onUnmounted, nextTick } from 'vue'
import { useStore } from 'vuex'
import $axios from '@/http'
import { chatItemType } from '@/type/socket'
import { chatMenuType } from '@/type/chat'
import { socketURL } from '@/http'
import msg from '@/components/msg/msg'
import Textarea from '@/components/Textarea/index.vue'
import Button from '@/components/button.vue'

type TChatType = {
  type: 'notic' | 'chat'
  message: string
}
const $store = useStore()
const content = ref<string>('')
const chatItem = ref<Array<chatItemType>>([]) //所有谈话内容
const leftMenuItem = ref<Array<chatMenuType>>([])
const newToUserId = ref<number | null>(null)
const type = ref<string>('chat')
const reConnectTime = ref<number>(0)
const ws = ref<WebSocket | null>(null)
const heartCheckTime = ref<number | null>(null)
onMounted(() => {
  if (ifLogin.value) {
    initContent()
    if ($store.getters.user.status === '876ea4f21078c7d38e3b0bdc74a') {
      initChat()
    }
    initJoinRoom()
    tokeContent()
  }
})
const innerH = computed(() => (document.body.clientWidth < 765 ? window.innerHeight - 63 : false))
// 移动端浏览器要额外适配 通过window.innerHeight
const innerH1 = computed(() => (document.body.clientWidth < 765 ? window.innerHeight - 103 : false))
const ifLogin = computed(() => $store.getters.user.username)
const status = computed(() => $store.getters.user.status)
//房间名字一开始房间名字为各自的用户名 在不断更换房间的时候会改变管理员的username
//左边对话列表
const initChat = () => {
  $axios
    .get('/chat/lastSearch')
    .then((res: any) => {
      if (res.data.error === -1) {
        leftMenuItem.value = res.data.data
      } else {
        leftMenuItem.value = []
      }
    })
    .catch(() => {
      alert('服务器出现问题如多次出现请联系博主')
    })
}
const seeCurrentUserMessage = (message: Array<chatItemType>) => {
  const chatBox: HTMLElement | null = document.querySelector('.chatBoxBox')
  setTimeout(() => {
    chatBox && (chatBox.scrollTop = chatBox.scrollHeight)
  })
  chatItem.value = message
}
//在初始阶段获取用户之前的对话记录
const initContent = (userId?: number, cb?: Function) => {
  if (status.value === '876ea4f21078c7d38e3b0bdc74a' && !userId) {
    msg.success('当前为管理员')
    return
  }
  $axios
    .get('/chat/search', {
      params: {
        userId: userId || $store.getters.user.id
      }
    })
    .then((res: any) => {
      if (res.data.error === -1) {
        chatItem.value = res.data.data
        cb && cb()
        const chatBox: HTMLElement | null = document.querySelector('.chatBoxBox')
        setTimeout(() => {
          chatBox && (chatBox.scrollTop = chatBox.scrollHeight)
        })
      } else {
        // 错误提示
        chatItem.value = []
      }
    })
}
//加入新房间
const joinNewRoomToSendMessage = (toUserId: number) => {
  if (toUserId === newToUserId.value) {
    msg.error('您已经在该房间里')
    return
  }
  newToUserId.value = toUserId
  initContent(toUserId, () => {
    startSendMessage({
      type: 'notic',
      message: `${$store.getters.user.realname}加入房间`
    })
  })
}
//离开谈话
const leavetoke = () => {
  if (heartCheckTime.value) {
    clearInterval(heartCheckTime.value)
  }
  startSendMessage({ type: 'notic', message: `${$store.getters.user.realname}离开房间` })
  ws.value?.close()
}
//正在谈话
const tokeContent = () => {
  if (!ws.value) {
    msg.error('连接失败')
    // reConnect();
    return
  }
  ws.value.onclose = () => {
    // reConnect();
  }
  ws.value.onerror = () => {
    if (reConnectTime.value >= 10) {
      msg.error('与聊天室断开连接！')
      return
    }
    msg.error('连接错误。。。正在尝试重新链接')
    setTimeout(() => {
      reConnect()
    }, 3500)
  }
  ws.value.onmessage = ({ data }) => {
    const messageData = JSON.parse(data)
    chatItem.value.push(messageData)
    if (messageData.type === 'notic') {
    } else {
      if (leftMenuItem.value.find((item) => item.userId === messageData.userId || item.userId === messageData.toUserId)) {
        leftMenuItem.value.forEach((element, index) => {
          if (element.userId === messageData.userId) {
            // 如果相同用户发了很多消息
            if (element.message !== messageData.message || element.userId === messageData.toUserId) {
              //判断上一个消息和当前消息是否相同
              element.message = messageData.message
            }
            leftMenuItem.value.splice(index, 1)
            leftMenuItem.value.unshift(element)
          }
        })
      } else {
        //深拷贝
        let a = JSON.parse(JSON.stringify(messageData))
        leftMenuItem.value.unshift(a)
      }
    }
    const chatBox: HTMLElement | null = document.querySelector('.chatBoxBox')
    setTimeout(() => {
      chatBox && (chatBox.scrollTop = chatBox.scrollHeight)
    })
  }
  ws.value.onclose = () => {
    // msg.success("连接断开");
  }
}
const reConnect = () => {
  reConnectTime.value++
  initJoinRoom()
  tokeContent()
}
// 初始化加入房间 进入群聊
const initJoinRoom = () => {
  if (ifLogin) {
    ws.value = new WebSocket(`${socketURL}/socket/${$store.getters.user.id}`)
  }
  ws.value &&
    (ws.value.onopen = () => {
      if (reConnectTime.value === 0) {
        msg.success(`欢迎${$store.getters.user.realname}进入房间`)
      } else {
        msg.success('重连成功')
        initContent()
        initChat()
      }
      reConnectTime.value = 0
    })
  if (heartCheckTime.value) {
    clearInterval(heartCheckTime.value)
  }
  // 心跳检测
  heartCheckTime.value = setInterval(() => {
    heartCheck()
  }, 40000)
}
const heartCheck = () => {
  const sendMessage = {
    userId: $store.getters.user.id,
    type: 'heart'
  }
  ws.value?.send(JSON.stringify(sendMessage))
}
const sendMessage = () => {
  ws.value && startSendMessage()
}
const startSendMessage = (type: TChatType = { type: 'chat', message: '' }) => {
  if (!ws.value || !content.value.trim()) {
    return
  }
  const sendMessage = {
    message: type.message || content.value,
    userId: $store.getters.user.id,
    toUserId: newToUserId.value || 17,
    type: type.type,
    realname: $store.getters.user.realname,
    avatar: $store.getters.user.avatar
  }
  if (sendMessage.toUserId === sendMessage.userId) {
    return
  }
  ws.value?.send(JSON.stringify(sendMessage))
  content.value = ''
}
onUnmounted(() => {
  // ws?.value?.send();
  leavetoke()
})
</script>

<style lang="scss" scoped>
// @import url("../../css/mobile/mvsocket.scss");
@import '../../css/pc/socket.scss';
</style>
